﻿using System;
using System.Collections.Generic;
using System.Text;
using GG.Core;
using ESBasic.ObjectManagement.Managers;
using ESBasic.Security;

namespace GG.Server
{
    /// <summary>
    /// 在内存中模拟数据库，正式项目中，可以将该类的操作移植到真实的数据库。
    /// *********** 注意：该模拟只是一个简单的演示，实际应用中，需要格外注意 数据表结构的设计、性能的优化、缓存的使用，等等！！！！！！！！！！！！！！
    /// </summary>
    internal class VirtualDB :IGGPersister
    {
        private ObjectManager<string, User> userTable = new ObjectManager<string, User>(); // key:用户ID 。 Value：用户信息
        private ObjectManager<string, List<string>> friendTable = new ObjectManager<string, List<string>>(); // key:用户ID 。 Value：好友列表
        private ObjectManager<string, Group> groupTable = new ObjectManager<string, Group>();  // key:组ID 。 Value：Group信息
        private ObjectManager<string, List<OfflineMessage>> offlineMessageTable = new ObjectManager<string, List<OfflineMessage>>();//key:用户ID 。 
        private ObjectManager<string, List<OfflineFileItem>> offlineFileTable = new ObjectManager<string, List<OfflineFileItem>>();//key:用户ID 。 
        public VirtualDB()
        {
            string pwdMD5 = SecurityHelper.MD5String("1");
            //内置测试的用户
            this.userTable.Add("10000", new User("10000", pwdMD5, "Martin", "每一天都是崭新的！", 0));
            this.userTable.Add("10001", new User("10001", pwdMD5, "David", "加油，努力。", 1));
            this.userTable.Add("10002", new User("10002", pwdMD5, "Tom", "随风而逝...", 2));
            this.userTable.Add("10003", new User("10003", pwdMD5, "John", "有事请call我", 3));
            this.userTable.Add("10004", new User("10004", pwdMD5, "Steven", "岁月是把杀猪刀", 4));

            //内置的测试用户是好友关系
            this.friendTable.Add("10000", new List<string>(new string[] { "10001", "10002", "10003", "10004" }));
            this.friendTable.Add("10001", new List<string>(new string[] { "10000", "10002", "10003", "10004" }));
            this.friendTable.Add("10002", new List<string>(new string[] { "10001", "10000", "10003", "10004" }));
            this.friendTable.Add("10003", new List<string>(new string[] { "10001", "10002", "10000", "10004" }));
            this.friendTable.Add("10004", new List<string>(new string[] { "10001", "10002", "10003", "10000" }));

            //内置G001组，所有测试用户都属于该组
            this.groupTable.Add("G001", new Group("G001" ,"测试群1", new List<string>(new string[] {"10000", "10001", "10002", "10003", "10004" })));

            //内置G002组， "10000", "10001" 测试用户属于该组
            this.groupTable.Add("G002", new Group("G002", "测试群2", new List<string>(new string[] { "10000", "10001" })));
        }

        #region UserTable       

        /// <summary>
        /// 插入一个新用户。
        /// </summary>      
        public void InsertUser(User user)
        {
            this.userTable.Add(user.ID, user);
        }

        /// <summary>
        /// 目标帐号是否已经存在？
        /// </summary>    
        public bool IsUserExist(string userID)
        {
            return this.userTable.Contains(userID);
        }

        /// <summary>
        /// 根据ID获取用户信息。
        /// </summary>        
        public User GetUser(string userID)
        {
            return this.userTable.Get(userID);
        }

        public ChangePasswordResult ChangePassword(string userID, string oldPasswordMD5, string newPasswordMD5)
        {
            User user = this.userTable.Get(userID);
            if (user == null)
            {
                return ChangePasswordResult.UserNotExist;
            }

            if (user.PasswordMD5 != oldPasswordMD5)
            {
                return ChangePasswordResult.OldPasswordWrong;
            }

            user.PasswordMD5 = newPasswordMD5;         
            return ChangePasswordResult.Succeed;
        }
        #endregion

        #region FriendTable
        /// <summary>
        /// 获取某个用户的好友列表。
        /// </summary>      
        public List<string> GetFriends(string userID)
        {
            if (!this.friendTable.Contains(userID))
            {
                return new List<string>();
            }

            return this.friendTable.Get(userID);
        }

        /// <summary>
        /// 添加好友，建立双向关系
        /// </summary>  
        public void AddFriend(string ownerID, string friendID)
        {
            if (!this.friendTable.Contains(ownerID))
            {
                this.friendTable.Add(ownerID, new List<string>());
            }
            this.friendTable.Get(ownerID).Add(friendID);

            if (!this.friendTable.Contains(friendID))
            {
                this.friendTable.Add(friendID, new List<string>());
            }
            this.friendTable.Get(friendID).Add(ownerID);
        }

        public void RemoveFriend(string ownerID, string friendID)
        {
            this.friendTable.Get(ownerID).Remove(friendID);
            this.friendTable.Get(friendID).Remove(ownerID);
        }
        #endregion

        #region GroupTable
        /// <summary>
        /// 获取某用户所在的所有组列表。
        /// 建议：可将某个用户所在的组ID列表挂接在用户资料的某个字段上，以避免遍历计算。
        /// </summary>       
        public List<Group> GetMyGroups(string userID)
        {
            List<Group> groups = new List<Group>();
            foreach (Group group in this.groupTable.GetAll())
            {
                if (group.Members.Contains(userID))
                {
                    groups.Add(group);
                }
            }
            return groups;
        }

        /// <summary>
        /// 获取某个组
        /// </summary>       
        public Group GetGroup(string groupID)
        {
            return this.groupTable.Get(groupID);     
        }

        /// <summary>
        /// 创建组
        /// </summary>       
        public CreateGroupResult CreateGroup(string creatorID, string groupID, string groupName)
        {
            if (this.groupTable.Contains(groupID))
            {
                return CreateGroupResult.GroupExisted;
            }

            List<string> members = new List<string>() ;
            members.Add(creatorID) ;
            Group group = new Group(groupID, groupName, members);
            this.groupTable.Add(groupID, group);
            return CreateGroupResult.Succeed;
        }

        /// <summary>
        /// 推出组
        /// </summary>       
        public void QuitGroup(string userID, string groupID)
        {
            Group group = this.groupTable.Get(groupID);
            if (group != null)
            {
                group.Members.Remove(userID);
            }
        }

        /// <summary>
        /// 加入某个组。
        /// </summary>        
        public JoinGroupResult JoinGroup(string userID, string groupID)
        {
            Group group = this.groupTable.Get(groupID);
            if (group == null)
            {
                return JoinGroupResult.GrpupNotExist;
            }
            if (!group.Members.Contains(userID))
            {
                group.Members.Add(userID);
            }

            return JoinGroupResult.Succeed;
        }

        /// <summary>
        /// 获取某个用户的所有组友。
        /// 建议：由于该方法经常被调用，可将组友关系缓存在内存中，而非每次都遍历计算一遍。
        /// </summary>        
        public List<string> GetGroupmates(string userID)
        {
            List<string> groupmates = new List<string>();
            foreach (Group group in this.groupTable.GetAll())
            {
                if (group.Members.Contains(userID))
                {
                    foreach (string memberID in group.Members)
                    {
                        if (memberID != userID && !groupmates.Contains(memberID))
                        {
                            groupmates.Add(memberID);
                        }
                    }
                }
            }
            return groupmates;
        }
        #endregion

        #region OfflineMessage
         /// <summary>
        /// 存储离线消息。
        /// </summary>       
        /// <param name="msg">要存储的离线消息</param>
        public void StoreOfflineMessage(OfflineMessage msg)
        {
            if (!this.offlineMessageTable.Contains(msg.DestUserID))
            {
                this.offlineMessageTable.Add(msg.DestUserID, new List<OfflineMessage>());
            }

            this.offlineMessageTable.Get(msg.DestUserID).Add(msg);
        }

        /// <summary>
        /// 提取目标用户的所有离线消息。
        /// </summary>       
        /// <param name="destUserID">接收离线消息用户的ID</param>
        /// <returns>属于目标用户的离线消息列表，按时间升序排列</returns>
        public List<OfflineMessage> PickupOfflineMessage(string destUserID)
        {
            if (!this.offlineMessageTable.Contains(destUserID))
            {
                return new List<OfflineMessage>();
            }

            List<OfflineMessage> list = this.offlineMessageTable.Get(destUserID);
            this.offlineMessageTable.Remove(destUserID);
            return list;
        }
        #endregion

        #region OfflineFile
        /// <summary>
        /// 将一个离线文件条目保存到数据库中。
        /// </summary>     
        public void StoreOfflineFileItem(OfflineFileItem item)
        {
            if (!this.offlineFileTable.Contains(item.AccepterID))
            {
                this.offlineFileTable.Add(item.AccepterID, new List<OfflineFileItem>());
            }

            this.offlineFileTable.Get(item.AccepterID).Add(item);
        }

        /// <summary>
        /// 从数据库中提取接收者为指定用户的所有离线文件条目。
        /// </summary>       
        public List<OfflineFileItem> PickupOfflineFileItem(string accepterID)
        {
            if (!this.offlineFileTable.Contains(accepterID))
            {
                return new List<OfflineFileItem>();
            }

            List<OfflineFileItem> list = this.offlineFileTable.Get(accepterID);
            this.offlineFileTable.Remove(accepterID);
            return list;
        }

        #endregion
    }    
}
